Ok, after trying many things I finally have it working. I don't understand why it works, though, so I would appreciate an education:
ch5->CommutationOffset = 0.25 * 20000/50; // offset ~1/4 of encoder count per pole
The position counter in the axis window would generally not be zero. In fact, it was varying tens of counts. And the performance of the motor would depend on that number (anything from moving nicely to running away like a jet engine)
I found that executing the setup program several times back to back could get the count to zero, or at least single digit deviations.
I tried many things to get to a consistent number here. I tried to cycle the Write4PH trough a loop, increasing strength and or angle while doing so, and a lot of other stuff.
The one thing that finally got me consistent behavior is running above code 2 or 3 times. After doing that, the count generally hovers at about +10-11
That already lets the stepper work great. Though I found that adding +5 encoder counts gives me a more symmetrical behavior in the step response.
Why does this work, but manually phasing does not? Complete code:
#include "KMotionDef.h"
void main()
{
WriteSnapAmp(SNAP0+SNAP_PEAK_CUR_LIMIT0,9); // current limit
WriteSnapAmp(SNAP0+SNAP_PEAK_CUR_LIMIT1,9); // current limit
Delay_sec(0.1); // wait for any fault to clear
ch5->InputMode=NO_INPUT_MODE;
ch5->OutputMode=MICROSTEP_MODE;
ch5->Vel=20.000000;
ch5->Accel=100.000000;
ch5->Jerk=1000.000000;
ch5->P=0.050000;
ch5->I=0.000000;
ch5->D=5.000000;
ch5->FFAccel=0.000000;
ch5->FFVel=0.000000;
ch5->MaxI=200.000000;
ch5->MaxErr=1000000.000000;
ch5->MaxOutput=200.000000;
ch5->DeadBandGain=1.000000;
ch5->DeadBandRange=0.000000;
ch5->InputChan0=8;
ch5->InputChan1=9;
ch5->OutputChan0=10;
ch5->OutputChan1=11;
ch5->LimitSwitchOptions=0x0;
ch5->InputGain0=1.000000;
ch5->InputGain1=1.000000;
ch5->InputOffset0=0.000000;
ch5->InputOffset1=0.000000;
ch5->invDistPerCycle=1.000000;
ch5->Lead=0.000000;
ch5->MaxFollowingError=1000000000.000000;
ch5->StepperAmplitude=40.000000;
ch5->iir[0].B0=1.000000;
ch5->iir[0].B1=0.000000;
ch5->iir[0].B2=0.000000;
ch5->iir[0].A1=0.000000;
ch5->iir[0].A2=0.000000;
ch5->iir[1].B0=1.000000;
ch5->iir[1].B1=0.000000;
ch5->iir[1].B2=0.000000;
ch5->iir[1].A1=0.000000;
ch5->iir[1].A2=0.000000;
ch5->iir[2].B0=0.0566048;
ch5->iir[2].B1=0.11321;
ch5->iir[2].B2=0.0566048;
ch5->iir[2].A1=1.22804;
ch5->iir[2].A2=-0.454462;
DefineCoordSystem(5,-1,-1,-1);
DisableAxis(5);
Write4PH(ch5,100,0); // energize a pole
Delay_sec(2); // wait
Zero(5);
ch5->InputMode=ENCODER_MODE;
ch5->OutputMode=BRUSHLESS_4PH_MODE;
ch5->CommutationOffset = 0.25 * 20000/50; // offset ~1/4 of encoder count per pole
ch5->invDistPerCycle= 1.0 * 50.0/20000.0; // 200 step stepper -> 50 poles; 5000 line encoder -> 20000 counts per revolution.
EnableAxisDest(5, 0.0);
DisableAxis(5);
Write4PH(ch5,100,0); // energize a pole
Delay_sec(2); // wait
Zero(5);
ch5->InputMode=ENCODER_MODE;
ch5->OutputMode=BRUSHLESS_4PH_MODE;
ch5->CommutationOffset = 0.25 * 20000/50; // offset ~1/4 of encoder count per pole
ch5->invDistPerCycle= 1.0 * 50.0/20000.0; // 200 step stepper -> 50 poles; 5000 line encoder -> 20000 counts per revolution.
EnableAxisDest(5, 0.0);
DisableAxis(5);
Write4PH(ch5,100,0); // energize a pole
Delay_sec(2); // wait
Zero(5);
ch5->InputMode=ENCODER_MODE;
ch5->OutputMode=BRUSHLESS_4PH_MODE;
ch5->CommutationOffset = 0.25 * 20000/50 +3; // offset ~1/4 of encoder count per pole
ch5->invDistPerCycle= 1.0 * 50.0/20000.0; // 200 step stepper -> 50 poles; 5000 line encoder -> 20000 counts per revolution.
EnableAxisDest(5, 0.0);
Delay_sec(1.0); // wait
float position = ch5->Position; // save position
Delay_sec(0.10); // wait
position += ch5->Position; // save position
Delay_sec(0.10); // wait
position += ch5->Position; // save position
Delay_sec(0.10); // wait
position += ch5->Position; // save position
Delay_sec(0.10); // wait
printf("position: %f \n",position/4);
}
---In DynoMotion@yahoogroups.com, <homeloan@...> wrote :
It actually moves much faster than that. A revolution about every second or two. I did put a mark on the shaft before the 100 rotations. No lost steps as far as I can tell.
---In DynoMotion@yahoogroups.com, <tk@...> wrote :
Ok thanks for that.
Velocity is set crazy slow (10/20000/60 = 0.000008 RPM)
I don't understand why moving fast would "get stuck and
vibrate". If the commutation is working correctly it shouldn't
ever get stuck. A large error should simply give max torque in
one direction. If the encoder counts are lost the commutation
would go wrong and likely get stuck. You might run a test to see
if the encoder position has drifted after attempting to move
fast. You should probably figure out what is happening before
going forward.
Otherwise I'd suggest Tuning:
#1 add a 2nd order Low Pass filter at 1000Hz Q=1.4 in the 3rd
Filter position to smooth out output spikes that will be caused by
D gain taking the derivative of the Encoder (which consists of
integer steps).
#2 add/increase D gain to a point where the system goes unstable,
then back off like 30%
#3 see if P gain can then be increased
#4 You might also try tweaking the Commutation offset by a few
counts to see if performance can be improved.
HTH
Regards
TK
Yes, this is configured as 4
phase brushless. The encoder is mounted directly to the
shaft.
The motor can do 100 revs, but in order to do that I had
to configure the velocity parameter down quite a bit.
Otherwise the motor would get stuck and vibrate - I guess
because of the proportional gain.
Here is the complete configuration:
#include "KMotionDef.h"
// Configure SnapAMP for 2 stepper motors in Optical Table
Lathe
void main()
{
WriteSnapAmp(SNAP0+SNAP_PEAK_CUR_LIMIT0,9); //
current limit
WriteSnapAmp(SNAP0+SNAP_PEAK_CUR_LIMIT1,9); //
current limit
Delay_sec(0.1); // wait for any fault to clear
ch5->InputMode=NO_INPUT_MODE;
ch5->OutputMode=MICROSTEP_MODE;
ch5->Vel=10.000000;
ch5->Accel=100.000000;
ch5->Jerk=1000.000000;
ch5->P=0.100000;
ch5->I=0.000000;
ch5->D=0.000000;
ch5->FFAccel=0.000000;
ch5->FFVel=0.000000;
ch5->MaxI=200.000000;
ch5->MaxErr=1000000.000000;
ch5->MaxOutput=100.000000;
ch5->DeadBandGain=1.000000;
ch5->DeadBandRange=0.000000;
ch5->InputChan0=8;
ch5->InputChan1=9;
ch5->OutputChan0=10;
ch5->OutputChan1=11;
ch5->LimitSwitchOptions=0x0;
ch5->InputGain0=1.000000;
ch5->InputGain1=1.000000;
ch5->InputOffset0=0.000000;
ch5->InputOffset1=0.000000;
ch5->invDistPerCycle=1.000000;
ch5->Lead=0.000000;
ch5->MaxFollowingError=1000000000.000000;
ch5->StepperAmplitude=40.000000;
ch5->iir[0].B0=1.000000;
ch5->iir[0].B1=0.000000;
ch5->iir[0].B2=0.000000;
ch5->iir[0].A1=0.000000;
ch5->iir[0].A2=0.000000;
ch5->iir[1].B0=1.000000;
ch5->iir[1].B1=0.000000;
ch5->iir[1].B2=0.000000;
ch5->iir[1].A1=0.000000;
ch5->iir[1].A2=0.000000;
ch5->iir[2].B0=1.000000;
ch5->iir[2].B1=0.000000;
ch5->iir[2].B2=0.000000;
ch5->iir[2].A1=0.000000;
ch5->iir[2].A2=0.000000;
DefineCoordSystem(5,-1,-1,-1); //define ch4 as x and
ch5 as y; z and a disabled
DisableAxis(5);
Write4PH(ch5,80.0, 0.0); // energize a pole
Delay_sec(4.0); // wait
Zero(5);
ch5->InputMode=ENCODER_MODE;
ch5->OutputMode=BRUSHLESS_4PH_MODE;
ch5->CommutationOffset = 0.25 * 20000/50; //
offset ~1/4 of encoder count per pole
ch5->invDistPerCycle= 1.0 * 50.0/20000.0; // 200
step stepper -> 50 poles; 5000 line encoder -> 20000
counts per revolution.
EnableAxisDest(5, 2000000.0);
//Delay_sec(1.0); // wait
//DisableAxis(5); // make sure the axis is disabled
and not writing to SnapAmp
}
---In
DynoMotion@yahoogroups.com,
<tk@...> wrote :
It looks pretty nasty.
So this is 4 phase brushless correct? Encoder
mounted to motor
shaft?
The Commutation is verified to work properly? (ie you
can move
100 motor revs and the performance doesn't change)
It might just require better tuning. This is a torque
servo and
will be theoretically unstable with just P gain.
What are all your settings?
Regards
TK
Ok, I finally got the encoder and new motor
in. 5000
lines per revolution. Everything checks out ok
in
principle. The motor is not mounted yet, so
rapid
movements cause crazy oscillations, but you
mentioned that
before.
Anyway, I am attaching both a move and a step
for a small
movement. I have done larger, slow movements,
and they
seem to work as well. I think one can clearly
see the
torque ripple between individual steps in the
position. Is
that expected? At rest, there is a little
vibration - but
its generally less than +- 5 encoder counts.
I would like some directions as to what to do
from here.
Should I run any more tests/tuning before
mounting? What
can I do that is helpful to add to the wiki?